package com.hilinos.gb.gb28181.processor;

import com.hilinos.gb.gb28181.processor.request.IRequestProcessor;
import com.hilinos.gb.gb28181.processor.request.impl.OtherRequestProcessor;
import com.hilinos.gb.gb28181.processor.response.IResponseProcessor;
import com.hilinos.gb.gb28181.processor.response.impl.OtherResponseProcessor;
import gov.nist.javax.sip.SipStackImpl;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.stack.SIPServerTransaction;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.sip.*;
import javax.sip.header.CSeqHeader;
import javax.sip.header.HeaderFactory;
import javax.sip.header.ViaHeader;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import javax.sip.message.Response;

/**
 * 生成sip处理器
 * INVITE,REGISTER,ACK,BYE,MESSAGE,CANCEL,SUBSCRIBE
 * 其他的放到了Other
 */
@Slf4j
@Component
public class SipProcessorFactory {

    @Autowired
    @Qualifier("tcpProvider")
    private SipProvider tcpSipProvider;

    @Autowired
    @Qualifier("udpProvider")
    private SipProvider udpSipProvider;

    @Autowired
    private ApplicationContext context;

    @Autowired
    private OtherResponseProcessor otherResponseProcessor;

    public IRequestProcessor createRequestProcessorFactory(RequestEvent requestEvent) {
        if (log.isDebugEnabled()) {
            log.debug("收到消息:\n{}", requestEvent.getRequest().toString());
        }
        try {
            return context.getBean(requestEvent.getRequest().getMethod().toLowerCase() + "RequestProcessor", IRequestProcessor.class);
        } catch (BeansException e) {
            return context.getBean("otherRequestProcessor", IRequestProcessor.class);
        }
    }

    @SneakyThrows
    public void responseAck(RequestEvent evt) {
        Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
        getServerTransaction(evt).sendResponse(response);
    }

    public IResponseProcessor createResponseProcessorFactory(ResponseEvent responseEvent) {
        if (log.isDebugEnabled()) {
            log.debug("收到消息:\n{}", responseEvent.getResponse().toString());
        }
        try {
            Response response = responseEvent.getResponse();
            CSeqHeader cseqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
            String method = cseqHeader.getMethod();
            return context.getBean(method + "RequestProcessor", IResponseProcessor.class);
        } catch (Exception e) {
            return otherResponseProcessor;
        }
    }

    public ServerTransaction getServerTransaction(RequestEvent evt) {
        Request request = evt.getRequest();
        ServerTransaction serverTransaction = evt.getServerTransaction();
        // 判断TCP还是UDP
        boolean isTcp = false;
        ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
        String transport = reqViaHeader.getTransport();
        if (transport.equals("TCP")) {
            isTcp = true;
        }

        if (serverTransaction == null) {
            try {
                if (isTcp) {
                    SipStackImpl stack = (SipStackImpl) tcpSipProvider.getSipStack();
                    serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest) request, true);
                    if (serverTransaction == null) {
                        serverTransaction = tcpSipProvider.getNewServerTransaction(request);
                    }
                } else {
                    SipStackImpl stack = (SipStackImpl) udpSipProvider.getSipStack();
                    serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest) request, true);
                    if (serverTransaction == null) {
                        serverTransaction = udpSipProvider.getNewServerTransaction(request);
                    }
                }
            } catch (TransactionAlreadyExistsException e) {
                e.printStackTrace();
            } catch (TransactionUnavailableException e) {
                e.printStackTrace();
            }
        }
        return serverTransaction;
    }

    public HeaderFactory getHeaderFactory() {
        try {
            return SipFactory.getInstance().createHeaderFactory();
        } catch (PeerUnavailableException e) {
            e.printStackTrace();
        }
        return null;
    }

    public MessageFactory getMessageFactory() {
        try {
            return SipFactory.getInstance().createMessageFactory();
        } catch (PeerUnavailableException e) {
            e.printStackTrace();
        }
        return null;
    }


}
